using System;
using System.Collections.Generic;
using System.Text;

namespace Spring08Lab2
{
    /// <summary>
    /// A class to represent complex numbers
    /// </summary>
    public class Complex
    {
        #region instance vars and properties
        private double real;

        public double Real
        {
            get { return real; }
            set { real = value; }
        }

        private double imaginary;

        public double Imaginary
        {
            get { return imaginary; }
            set { imaginary = value; }
        }
        #endregion
        #region constructors
        public Complex()
            : this(0, 0)
        {

        }
		
		public override string ToString()
		{
			return("" + this.real + " + " + this.imaginary + "i");
		}

        public Complex(double r, double i)
        {
            real = r;
            imaginary = i;
        }

        #endregion
        #region operations
        /// <summary>
        /// This provides the equality operator.
        /// Recall that two complex numbers are 
        /// equal if their real parts are equal and 
        /// their imaginary parts are equal.
        /// </summary>
        /// <param name="lhs">left hand side</param>
        /// <param name="rhs">right hand side</param>
        /// <returns>true if lhs is equal to rhs, false otherwise</returns>
        /// <example>
        /// Complex c1 = new Complex (4, 5);
        /// Complex c2 = new Complex (4, 5);
        /// c1 == c2   //should return true
        /// </example>
        public static bool operator==(Complex lhs, Complex rhs)
        {
            return ((lhs.Real == rhs.Real) && (lhs.Imaginary == rhs.Imaginary));
        }
        /// <summary>
        /// Same as == above
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            Complex c = (Complex)obj;
            return this == c;
        }
        /// <summary>
        /// Required if == and Equals implemented
        /// Just compute the hash as real * imaginary 
        /// </summary>
        /// <returns>hashcode for this class</returns>
        public override int GetHashCode()
        {
            return (int)(Imaginary * Real);
        }
        /// <summary>
        /// Provides the inequality operator.  
        /// Converse of == above
        /// </summary>
        /// <param name="lhs">left hand complex</param>
        /// <param name="rhs">right hand complex</param>
        /// <returns>true if lhs is not equal, false otherwise</returns>
        /// <example>
        ///  Complex c1 = new Complex (4, 5);
        /// Complex c2 = new Complex (6, 5);
        /// c1 == c2   //should return true
        ///</example>
        public static bool operator !=(Complex lhs, Complex rhs)
        {
            return !((lhs.Real == rhs.Real) && (lhs.Imaginary == rhs.Imaginary));
        }
        /// <summary>
        /// Return the sum of two complex numbers.
        /// Recall the sum is the sum of the real parts
        /// and the sum of the imaginary parts.
        /// </summary>
        /// <param name="lhs">the left complex</param>
        /// <param name="rhs">the right complex</param>
        /// <returns>a new complex number representing the sum.  lhs and rhs are unchanged</returns>
        /// <example>
        ///Complex c1 = new Complex (4, 5);
        /// Complex c2 = new Complex (4, 5);
        /// c1 + c2   //should Complex(8, 10) 
        ///</example>
        public static Complex operator +(Complex lhs, Complex rhs)
        {
            return new Complex(lhs.Real + rhs.Real, lhs.Imaginary + rhs.Imaginary);
        }
        /// <summary>
        /// Return the difference of two complex numbers.
        /// Recall the difference is the difference of the real parts
        /// and the difference of the imaginary parts.
        /// </summary>
        /// <param name="lhs">the left complex</param>
        /// <param name="rhs">the right complex</param>
        /// <returns>a new complex number representing the difference.  lhs and rhs are unchanged</returns>
        /// <example>
        ///Complex c1 = new Complex (4, 7);
        /// Complex c2 = new Complex (2, 3);
        /// c1 - c2   //should Complex(2, 4) 
        ///</example>
        public static Complex operator -(Complex lhs, Complex rhs)
        {
            return new Complex(lhs.Real - rhs.Real, lhs.Imaginary - rhs.Imaginary);
        }
        /// <summary>
        /// Return the product of two complex numbers.
        /// Recall that the product of (a+bi) * (c+di)
        /// is: (ac-bd) + (bc + ad)i
        /// </summary>
        /// <param name="lhs">the left side</param>
        /// <param name="rhs">the right side</param>
        /// <returns>the product as new complex.  lhs and rhs unchanged</returns>
        public static Complex operator *(Complex lhs, Complex rhs)
        {   
            double a = lhs.Real;
            double b = lhs.Imaginary;
            double c = rhs.Real;
            double d = rhs.Imaginary;

            return new Complex(a*c - b*d, b*c + a*d);
        }
        /// <summary>
        /// Return the quotient of two complex numbers
        /// Recall that the quotient of (a+bi) / (c+di) is:
        /// real part:  (ac+bd)/(c^2 + d^2)
        /// imaginary part: (bc - ad)/(c^2 + d^2)
        /// </summary>
        /// <param name="lhs">left side</param>
        /// <param name="rhs">right side</param>
        /// <returns>the quotient as a new complex.  lhs and rhs are unchanged</returns>
        public static Complex operator /(Complex lhs, Complex rhs)
        {
            double a = lhs.Real;
            double b = lhs.Imaginary;
            double c = rhs.Real;
            double d = rhs.Imaginary;

            double real = (a*c + b*d)/(c*c + d*d);
            double imag = (b*c - a*d)/(c*c + d*d);

            return new Complex(real, imag);
        }
        /// <summary>
        /// Compute the absolute value of the complex number c
        /// Recall the abs(a+bi) = square root of (a^2 + b^2)
        /// </summary>
        /// <returns>the absolute value</returns>
        public double Abs()
        {
            return Math.Sqrt(Real*Real + Imaginary*Imaginary);
        }

        /// <summary>
        /// Compute the polar coordinate magnitude of a complex number
        /// Recall for (a+bi) this is square root of (a^2 + b^2)
        /// </summary>
        /// <returns>the polar magnitude</returns>
        public double PolarMagnitude()
        {
            return Math.Sqrt(Real*Real + Imaginary*Imaginary);
        }
        /// <summary>
        /// Compute the polar coordinate angle of a complex number
        /// Recall that for (a+bi) this is the arctangent of (b/a)
        /// </summary>
        /// <returns>The polar coord</returns>
        public double PolarAngle()
        {
            return Math.Atan(Imaginary/Real);
        }
        /// <summary>
        /// Convert a polar coordinate radius and angle into a complex
        /// number.  Rounds both real and imaginary part to 2 decimal places
        /// Recall that for radius, angle:
        /// real part = radius * cosine (theta)
        /// imag part = radius * sine (theta)
        /// </summary>
        /// <param name="radius">the polar radius</param>
        /// <param name="theta">the polar coord angle in degrees</param>
        /// <returns>a new complex number based on r, theta</returns>
        public static  Complex ComputeFromPolar(double radius, double theta)
        {
            double real = Math.Round(radius * Math.Cos(theta/180*Math.PI), 2);
            double imag = Math.Round(radius * Math.Sin(theta/180*Math.PI), 2);

            return new Complex(real, imag);
        }
        #endregion
    }
}
